from django.db import transaction
from rest_framework import serializers
from rest_framework.relations import PrimaryKeyRelatedField

from apps.goods.models import SKU, GoodsCategory, SPU, SPUSpecification, SpecificationOption, SKUSpecification


# sku规格选项表的序列化器
class SKUSpecificationModelSerializer(serializers.ModelSerializer):
    spec_id = serializers.IntegerField()
    option_id = serializers.IntegerField()

    class Meta:
        model = SKUSpecification
        fields = ['spec_id', 'option_id']


class SKUSerializer(serializers.ModelSerializer):
    # 添加2个字段来接收 category_id 和 spu_id
    spu_id = serializers.IntegerField()
    category_id = serializers.IntegerField()

    # 自己定义spu和category字段为 StringRelatedField
    spu = serializers.StringRelatedField(read_only=True)
    category = serializers.StringRelatedField(read_only=True)

    # 默认只能读  不能写
    specs = SKUSpecificationModelSerializer(many=True)

    class Meta:
        model = SKU
        fields = '__all__'

    def create(self, validated_data):
        # sku_id  spec_id  option_id
        # validated_data只有通过序列化器验证后的字段
        # self.context.request.data
        # 1获取所有的规格选项数据  并且把specs从字典删除
        specs = validated_data.pop("specs")
        with transaction.atomic():
            save_point = transaction.savepoint()  # 创建事物的保存点
            try:
                # 2先保存sku到数据库  生成了sku对象  sku_id
                sku = SKU.objects.create(**validated_data)

                # 'specs': [{'spec_id': '6', 'option_id': 14}, {'spec_id': '7', 'option_id': 21}]

                # 3遍历specs 把数据保存 到SKUSpecification表中
                for spec in specs:
                    SKUSpecification.objects.create(sku=sku, **spec)
            except Exception as e:
                print(e)
                transaction.savepoint_rollback(save_point)  # 回滚到save_point位置
            else:
                transaction.savepoint_commit(save_point)

        # 4返回sku对象
        return sku

    def update(self, instance, validated_data):
        # 1 获取所有的规格选项数据 并且把specs从字典删除
        specs = validated_data.pop("specs")
        # 2 更新sku数据
        # 调用父类的update方法 更新sku
        super().update(instance, validated_data)

        # for attr,value in validated_data.items():
        #     setattr(instance, attr, value)
        # instance.save()

        # 3 更新sku和规格关系表的数据
        # sku  spec_id option_id
        # 烤鸭   颜色 黑色    版本 64
        #       颜色 金色    版本 128

        # 根据skuid和规格id找到旧数据烤鸭对应的SKUSpecification对象,修改选项
        for spec in specs:  # spec  {'spec_id': '6', 'option_id': 14}
            SKUSpecification.objects.filter(sku=instance, spec_id=spec.get("spec_id")).update(
                option_id=spec.get("option_id"))

        return instance


# 获取三级分类的序列化器
class GoodsCategoryModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = GoodsCategory
        fields = ['id', 'name']


# spu序列化器
class SPUModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = SPU
        fields = ['id', 'name']


# 选项的的序列化器
class SpecificationOptionModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = SpecificationOption
        fields = ['id', 'value']


# 规格的序列化器
class SpecsModelSerializer(serializers.ModelSerializer):
    # 添加选项的序列化器对象  在序列化规格的同时也把对应的选项全部获取到
    options = SpecificationOptionModelSerializer(many=True)

    class Meta:
        model = SPUSpecification
        fields = ['id', 'name', 'options']
